﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Kaesoft.Hospedaje.Entities;
using System.Collections.Generic;
using Kaesoft.Hospedaje.Common;
using Kaesoft.Hospedaje.Proxy;
using Kaesoft.Hospedaje.Proxy.AdministracionReference;
using System.Collections.ObjectModel;
using System.Linq;
using System.ComponentModel;

namespace Kaesoft.Hospedaje.Admin
{
    public class ArbolOpcionesPerfilViewModel : ViewModelBase
    {



        public event EventHandler EventoSinDatos;
        private ObservableCollection<Arbol> _lstOpciones;
        private Arbol _nodoSeleccinando;
        private Perfil perfilActual;
        private Arbol _seleccionado;
        private Perfil _perfilSeleccionado;
        private bool _esHabilitado;
        private List<PerfilOpcion> _listaPerfilOpcion;
        private List<PerfilOpcionOperacion> _listaPerfilOpcionOperacion;
        private Opcion _opcionSeleccionada;
        private List<PerfilOpcion> _listaPerfilOpcionEliminar;
        private List<PerfilOpcion> _listaPerfilOpcionAgregar;
        private List<PerfilOpcion> _listaPerfilOpcionActual;
        private List<PerfilOpcionOperacion> _listaPerfilOpcionOperacionActual;
        private List<PerfilOpcionOperacion> _lstPerfilOpcionOperacionAdd;
        private List<PerfilOpcionOperacion> _lstPerfilOpcionOperacionDelete;
        private List<PerfilOpcion> comparacion;
        private List<Operacion> _opreacionesSeleccionadas;
        public List<Opcion> ListaOpcionesTemporal { get; set; }
        public List<PerfilOpcion> ListaPerfilOpcionTemporal { get; set; }
        public List<PerfilOpcion> ListaPerfilOpcionTodos { get; set; }
        public List<Arbol> ListaArbolTemporal { get; set; }
        private ArbolPerfilViewModel viewModelArbolPerfil;
        public Guid opcion;
        public Guid perfilO;
        private ObservableCollection<PerfilOpcion> _collectionTem;
        private AdministracionPerfilViewModel viewModelAdministracionPerfil;
        public event EventHandler SetEdition;
        public event EventHandler SaveCompleted;
        public event EventHandler<EventArgs<bool>> EstadoProcesando;
        public event EventHandler<EventArgs<Arbol>> OnNodoSeleccionado;

        #region eventos

        public void OnEstadoProcesando(bool estado)
        {
            if (EstadoProcesando != null)
                EstadoProcesando(this, new EventArgs<bool>(estado));
        }


        public void OnSaveCompleted()
        {
            if (SaveCompleted != null)
                SaveCompleted(this, new EventArgs());
        }

        public void OnSetEdition()
        {
            if (SetEdition != null)
                SetEdition(this, new EventArgs());
        }



        #endregion

        #region Propiedades

        public ObservableCollection<PerfilOpcion> CollectionTemp
        {
            get { return _collectionTem; }
            set
            {
                if (_collectionTem != value)
                {
                    _collectionTem = value;
                    OnPropertyChanged("CollectionTemp");
                }
            }
        }

        public AdministracionPerfilViewModel ViewModelAdministracionPerfil
        {
            get { return viewModelAdministracionPerfil; }
            set
            {
                if (viewModelAdministracionPerfil != value)
                {
                    viewModelAdministracionPerfil = value;
                    OnPropertyChanged("ViewModelAdministracionPerfil");
                }
            }
        }



        //public ArbolOpcionesPerfilViewModel ViewModelArbolOpcionesPerfil
        //{
        //    get { return viewModelArbolOpcionesPerfil; }
        //    set
        //    {
        //        if (viewModelArbolOpcionesPerfil != value)
        //        {
        //            viewModelArbolOpcionesPerfil = value;
        //            OnPropertyChanged("ViewModelArbolOpcionesPerfil");
        //        }
        //    }
        //}

        public Perfil PerfilActual
        {
            get { return perfilActual; }
            set
            {
                if (perfilActual != value)
                {
                    perfilActual = value;
                    OnPropertyChanged("PerfilActual");
                }
            }
        }

        public ArbolPerfilViewModel ViewModelArbolPerfil
        {
            get { return viewModelArbolPerfil; }
            set
            {
                if (viewModelArbolPerfil != value)
                {
                    viewModelArbolPerfil = value;
                    OnPropertyChanged("ViewModelArbolPerfil");
                }
            }
        }

        public List<PerfilOpcionOperacion> LstPerfilOpcionOperacionAgergar
        {
            get { return _lstPerfilOpcionOperacionAdd; }
            set
            {
                if (_lstPerfilOpcionOperacionAdd != value)
                {
                    _lstPerfilOpcionOperacionAdd = value;
                    OnPropertyChanged("LstPerfilOpcionOperacionAgergar");
                }
            }
        }
        public List<PerfilOpcionOperacion> LstPerfilOpcionoperacionEliminar
        {
            get { return _lstPerfilOpcionOperacionDelete; }
            set
            {
                if (_lstPerfilOpcionOperacionDelete != value)
                {
                    _lstPerfilOpcionOperacionDelete = value;
                    OnPropertyChanged("LstPerfilOpcionoperacionEliminar");
                }
            }
        }

        public List<PerfilOpcionOperacion> ListaPerfilOpcionOperacionActual
        {
            get { return _listaPerfilOpcionOperacionActual; }
            set
            {
                if (_listaPerfilOpcionOperacionActual != value)
                {
                    _listaPerfilOpcionOperacionActual = value;
                    OnPropertyChanged("ListaPerfilOpcionOperacionActual");
                }
            }
        }

        public List<PerfilOpcion> ListaPerfilOpcionActual
        {
            get { return _listaPerfilOpcionActual; }
            set
            {
                if (_listaPerfilOpcionActual != value)
                {
                    _listaPerfilOpcionActual = value;
                    OnPropertyChanged("ListaPerfilOpcionActual");
                }
            }
        }


        public Opcion OpcionSeleccionada
        {
            get { return _opcionSeleccionada; }
            set
            {
                if (_opcionSeleccionada != value)
                {
                    _opcionSeleccionada = value;
                    OnPropertyChanged("OpcionSeleccionada");
                }
            }
        }
        public List<Operacion> OperacionesSeleccionadas
        {
            get { return _opreacionesSeleccionadas; }
            set
            {
                if (_opreacionesSeleccionadas != value)
                {
                    _opreacionesSeleccionadas = value;
                    OnPropertyChanged("OperacionesSeleccionadas");
                }
            }
        }
        public Perfil PerfilSeleccionado
        {
            get { return _perfilSeleccionado; }
            set
            {
                if (_perfilSeleccionado != value)
                {
                    _perfilSeleccionado = value;
                    OnPropertyChanged("PerfilSeleccionado");
                }
            }
        }

        public ObservableCollection<Arbol> ListaOpciones
        {
            get { return _lstOpciones; }
            set
            {
                if (_lstOpciones != value)
                {
                    _lstOpciones = value;
                    OnPropertyChanged("ListaOpciones");
                }
            }
        }
        public List<PerfilOpcionOperacion> ListaPerfilOpcionOperacion
        {
            get { return _listaPerfilOpcionOperacion; }
            set
            {
                if (_listaPerfilOpcionOperacion != value)
                {
                    _listaPerfilOpcionOperacion = value;
                    OnPropertyChanged("ListaPerfilOpcionOperacion");
                }
            }
        }
        public List<PerfilOpcion> ListaPerfilOpcion
        {
            get { return _listaPerfilOpcion; }
            set
            {
                if (_listaPerfilOpcion != value)
                {
                    _listaPerfilOpcion = value;
                    OnPropertyChanged("ListaPerfilOpcion");
                }
            }
        }
        public bool EsHabilitado
        {
            get { return _esHabilitado; }
            set
            {
                if (_esHabilitado != value)
                {
                    _esHabilitado = value;
                    OnPropertyChanged("EsHabilitado");
                }
                if (!_esHabilitado && !value)
                    OnPropertyChanged("EsHabilitado");
            }
        }

        public List<PerfilOpcion> ListaPerfilOpcionAgregar
        {
            get { return _listaPerfilOpcionAgregar; }
            set
            {
                if (_listaPerfilOpcionAgregar != value)
                {
                    _listaPerfilOpcionAgregar = value;
                    OnPropertyChanged("ListaPerfilOpcionAgregar");
                }
            }
        }

        public List<PerfilOpcion> ListaPerfilOpcionEliminar
        {
            get { return _listaPerfilOpcionEliminar; }
            set
            {
                if (_listaPerfilOpcionEliminar != value)
                {
                    _listaPerfilOpcionEliminar = value;
                    OnPropertyChanged("ListaPerfilOpcionEliminar");
                }
            }
        }
        //        /// <summary>
        //        /// Ejecuta la llamada a la consulta que carga las opciones en base al Identificador del padre 
        //        /// </summary>
        //        /// <param name="arbolSeleccionado"></param>
        public void CargarOpcionPorId(Arbol arbolSeleccionado)
        {
            #region Implementación
            _seleccionado = arbolSeleccionado;

            ProxyAdministracion.ListarArbolOpcionesPorIdAsync(((Opcion)_seleccionado.Entidad).idOpcion, ev => ListarArbolOpcionesPorIdCompleted(null, ev));
            #endregion
        }
        #endregion


        #region Constructor
        /// <summary>
        /// Ejecutado cuando selecciona un nodo del árbol
        /// </summary>
        /// <param name="parameter">Parámetro</param>
        private void SeleccionarNodo(object parameter)
        {
            if (OnNodoSeleccionado != null && parameter != null)
                OnNodoSeleccionado(null, new EventArgs<Arbol>((Arbol)parameter));
        }

        public Arbol NodoSeleccionado
        {
            get { return _nodoSeleccinando; }
            set
            {
                _nodoSeleccinando = value;
                OnPropertyChanged("NodoSeleccionado");
                SeleccionarNodo(value);
            }

        }

        public ArbolOpcionesPerfilViewModel()
        {
            InicializaPropiedades();

            InicializaArbol();
            OnNodoSeleccionado += (sender, ev) =>
            {
                OpcionSeleccionada = ev.Data.Entidad as Opcion;
            };


        }


        #endregion

        //#region
        //public event EventHandler<EventArgs<Arbol>> OnNodoSeleccionado;
        //        internal event EventHandler<EventArgs<bool>> SeleccionTerminada;
        //#endregion

        // <summary>
        /// Carga El titulo del arbol y el nivel 1 del mismo
        /// </summary>
        public void InicializaArbol()
        {
            if (!Design.IsInDesignModeStatic)
            {
                _seleccionado = null;
                CargarOpciones();
            }
        }

        private void CargarOpciones()
        {
            #region Implementación
            //OnEstadoProcesando(true);
            ProxyAdministracion.ListarArbolOpcionesAsync(ev => ListarArbolOpcionesCompleted(null, ev));
            #endregion
        }

        /// <summary>
        /// Metodo que se ejecuta al finalizar el metodo asincronico del ListarArbolOpcionesAsync
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListarArbolOpcionesCompleted(object sender, ListarArbolOpcionesCompletedEventArgs e)
        {

            //ListaOpciones = new List<Arbol>();
            List<Opcion> listaOpcionesInicial = new List<Opcion>();
            Dictionary<int, List<Opcion>> comparador = new Dictionary<int, List<Opcion>>() { { 0, e.Result }, { 1, new List<Opcion>() } };
            ListaArbolTemporal = new List<Arbol>();
            ListaOpcionesTemporal = new List<Opcion>();
            ListaPerfilOpcionTodos = new List<PerfilOpcion>();
            if (e.Error != null)
            {
                return;
            }
            if (e.Result.Count > 0)
            {
                if (PerfilSeleccionado != null)
                {
                    if (PerfilSeleccionado.idPerfil != Guid.Empty)
                    {
                        ProxyAdministracion.ObtenerPerfilPorIdAsync(PerfilSeleccionado.idPerfil, ev =>
                        {
                            if (ev.Error != null)
                                return;
                            CollectionTemp = new ObservableCollection<PerfilOpcion>(ev.Result.PerfilOpcions);
                            CollectionTemp.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(CollectionTemp_CollectionChanged);
                            CollectionTemp.ToList().ForEach(a =>
                            {
                                ((INotifyPropertyChanged)a).PropertyChanged += new PropertyChangedEventHandler(ArbolOpcionesPerfilViewModel_PropertyChanged);
                            });

                            ListaPerfilOpcionTemporal = ev.Result.PerfilOpcions.ToList();
                            ListaPerfilOpcionTodos = ev.Result.TodosLosRegistros;
                            //ListaPerfilOpcionTodos.ForEach(a =>
                            //{
                            //    ((INotifyPropertyChanged)a).PropertyChanged += new PropertyChangedEventHandler(ArbolOpcionesPerfilViewModel_PropertyChanged);
                            //});
                            ListaOpcionesTemporal = ev.Result.Opciones;
                            listaOpcionesInicial = ListaOpcionesTemporal.Where(a => a.idPadre == null).ToList();
                            comparador[1] = listaOpcionesInicial;

                            CargarArbolPorDemanda(comparador);
                            OnEstadoProcesando(false);
                        });
                    }
                }

                CargarArbolPorDemanda(comparador);
                OnEstadoProcesando(false);
            }

            
        }

        void ArbolOpcionesPerfilViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            IsDirty = true;
            OnSetEdition();
        }

        void CollectionTemp_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            IsDirty = true;
            OnSetEdition();
        }

        /// <summary>
        /// Carga Información de Opciones Hijas en base a una opción padre 
        /// </summary>
        /// <param name="comparador"></param>
        private void CargarArbolPorDemanda(Dictionary<int, List<Opcion>> comparador)
        {
            int nivelHijo;
            if (_seleccionado != null)
            {
                nivelHijo = _seleccionado.Nivel + 1;
                _seleccionado.ArbolHijo = new ObservableCollection<Arbol>();
            }

            else
            {
                nivelHijo = 1;
                ListaOpciones = new ObservableCollection<Arbol>();
            }
            int cuentaForeach = 0;
            comparador[0].ForEach(a =>
            {
                cuentaForeach++;
                bool opcionSeleccionada = false;
                if (ListaOpcionesTemporal != null)
                {
                    comparador[1].ForEach(l =>
                    {
                        if (l.idOpcion == a.idOpcion)
                            opcionSeleccionada = true;
                    });
                }
                else
                    opcionSeleccionada = false;
                if (_seleccionado != null)
                    _seleccionado.ArbolHijo.Add(new Arbol() { Id = Guid.NewGuid(), nombre = a.nombre, Entidad = a, Nivel = nivelHijo, Seleccionado = opcionSeleccionada, EnabledSeleccion = EsHabilitado });
                else
                    ListaOpciones.Add(new Arbol() { Id = Guid.NewGuid(), nombre = a.nombre, Entidad = a, Nivel = nivelHijo, Seleccionado = opcionSeleccionada, EnabledSeleccion = EsHabilitado });
               
            });

            if (_seleccionado != null)
            {
                _seleccionado.ArbolHijo.ToList().ForEach(a =>
                {
                    a.onSelectedChanged += a_onSelectedChanged;
                });
            }
            else
            {
                ListaOpciones.ToList().ForEach(a =>
                {
                    a.onSelectedChanged += a_onSelectedChanged;
                });
            }
        }

        void a_onSelectedChanged(object sender, EventArgs e)
        {
            Arbol a = sender as Arbol;

            #region implementacion SelectChanged
            if (a.Seleccionado)
            {
                ListaPerfilOpcion = new List<PerfilOpcion>();
                if (PerfilSeleccionado.idPerfil == Guid.Empty)
                {
                    PerfilSeleccionado = new Perfil()
                    {
                        borrado = false,
                        nombre = PerfilSeleccionado.nombre
                    };
                }
                else
                {
                    var existe = PerfilSeleccionado.PerfilOpcions.ToList().Where(cn => cn.idOpcion == ((Opcion)a.Entidad).idOpcion && cn.idPerfil == PerfilSeleccionado.idPerfil).FirstOrDefault();

                    if (existe == null)
                    {
                        opcion = ((Opcion)a.Entidad).idOpcion;
                        perfilO = PerfilSeleccionado.idPerfil;
                        CTemporal(opcion, perfilO);
                        ListaPerfilOpcionAgregar.Add(new PerfilOpcion()
                        {
                            idPerfil = PerfilSeleccionado.idPerfil,
                            idOpcion = ((Opcion)a.Entidad).idOpcion
                        });
                    }
                    else
                    {
                        opcion = ((Opcion)a.Entidad).idOpcion;
                        perfilO = PerfilSeleccionado.idPerfil;
                        CTemporal(opcion, perfilO);

                        ListaPerfilOpcionEliminar.ForEach(ex =>
                        {
                            if (ex.idOpcion == existe.idOpcion && ex.idPerfil == existe.idPerfil)
                            {
                                ListaPerfilOpcionAgregar.Add(new PerfilOpcion()
                                {
                                    idPerfil = PerfilSeleccionado.idPerfil,
                                    idOpcion = ((Opcion)a.Entidad).idOpcion
                                });
                            }
                        });
                    }
                }
            }
            else
            {
                var existe = PerfilSeleccionado.PerfilOpcions.ToList().Where(cn => cn.idOpcion == ((Opcion)a.Entidad).idOpcion && cn.idPerfil == PerfilSeleccionado.idPerfil).FirstOrDefault();
                opcion = ((Opcion)a.Entidad).idOpcion;
                CTemporalN(opcion);
                if (existe != null)

                    ListaPerfilOpcionEliminar.Add(new PerfilOpcion()
                    {
                        idPerfil = PerfilSeleccionado.idPerfil,
                        idOpcion = ((Opcion)a.Entidad).idOpcion
                    });
                else
                {
                    ListaPerfilOpcionAgregar.ForEach(ex =>
                    {
                        if (ex.idOpcion == ((Opcion)a.Entidad).idOpcion && ex.idPerfil == PerfilSeleccionado.idPerfil)
                        {
                            PerfilOpcion elemento = ListaPerfilOpcionAgregar.Where(pa => pa.idOpcion == ((Opcion)a.Entidad).idOpcion && pa.idPerfil == PerfilSeleccionado.idPerfil).FirstOrDefault();
                            if (elemento != null)
                                ListaPerfilOpcionAgregar.Remove(elemento);
                        }
                    });
                }
            }
            #endregion
        }


        /// <summary>
        /// Metodo que se ejecuta al finalizar el metodo asincronico del ListarArbolOpcionesPorIdAsync
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ListarArbolOpcionesPorIdCompleted(object sender, ListarArbolOpcionesPorIdCompletedEventArgs e)
        {
            if (e.Error != null)
                return;

            Dictionary<int, List<Opcion>> comparador = new Dictionary<int, List<Opcion>>() { { 0, e.Result }, { 1, ListaOpcionesTemporal } };
            if (e.Result.Count > 0)
            {
                _seleccionado.ArbolHijo = new ObservableCollection<Arbol>();
                CargarArbolPorDemanda(comparador);
            }
            else
            {
                EventoSinDatos(null, new EventArgs());
            }
        }




        private void InicializaPropiedades()
        {
            EsHabilitado = false;
            ListaPerfilOpcion = new List<PerfilOpcion>();
            comparacion = new List<PerfilOpcion>();
            // ViewModelArbolPerfil = new ArbolPerfilViewModel();
            // ResumenPerfilOpcionOperacion = new List<PerfilOpcionOperacionMensaje>();
            LstPerfilOpcionoperacionEliminar = new List<PerfilOpcionOperacion>();
            LstPerfilOpcionOperacionAgergar = new List<PerfilOpcionOperacion>();
            ListaPerfilOpcionOperacion = new List<PerfilOpcionOperacion>();
            ListaPerfilOpcionTemporal = new List<PerfilOpcion>();
            ListaPerfilOpcionEliminar = new List<PerfilOpcion>();
            ListaPerfilOpcionAgregar = new List<PerfilOpcion>();
            ListaPerfilOpcionActual = new List<PerfilOpcion>();
            ListaPerfilOpcionOperacionActual = new List<PerfilOpcionOperacion>();

            // DtyOperacionesSelecionadas = new Dictionary<Guid, List<Operacion>>();
        }

        public void CTemporalN(Guid poAgregar)
        {


            CollectionTemp.ToList().ForEach(b =>
            {
                if (poAgregar == b.idOpcion)
                {
                    //var existet = ListaPerfilOpcionTodos.Where(a => a.idOpcion == poAgregar && a.idPerfil == poPerfil).FirstOrDefault();
                    var existe = ListaPerfilOpcionTodos.Where(a => a.idOpcion == poAgregar).FirstOrDefault();
                    if (existe == null)
                    {
                        CollectionTemp.Remove(CollectionTemp.Where(a => a.idOpcion == poAgregar).FirstOrDefault());

                    }
                    else
                    {
                        if (b.borrado == true)
                        {
                            b.borrado = false;
                        }
                        else
                        {
                            b.borrado = true;
                        }
                    }
                }
            });
        }

        public void CTemporal(Guid poAgregar, Guid poPerfil)
        {
            var existet = ListaPerfilOpcionTodos.Where(a => a.idOpcion == poAgregar && a.idPerfil == poPerfil).FirstOrDefault();

            if (existet == null)
            {

                CollectionTemp.Add(new PerfilOpcion()
                {
                    idPerfil = poPerfil,
                    idOpcion = poAgregar,
                    borrado = false,

                });
            }
            else
            {

                ListaPerfilOpcionTodos.ForEach(c =>
                {
                    if (c.idOpcion == poAgregar && c.idPerfil == poPerfil)
                    {
                        c.borrado = false;
                        CollectionTemp.Add(c);
                    }
                });
            }
        }
        public void Guardar(Perfil PerfilActual)
        {

            OnEstadoProcesando(true);
            var opcionesGuardar = CollectionTemp.ToList();
            ActualizarPerfilOpcion(PerfilActual.nombre,
                                                        PerfilActual.idPerfil,
                                                         opcionesGuardar);

        }

        public void ActualizarPerfilOpcion(string perfilNombre, Guid perfilId, List<PerfilOpcion> poAgregar)
        {

            ProxyAdministracion.GuardarPerfilOpcionAsync(perfilNombre, perfilId, poAgregar, ev => GuardaPerfilOpcionesCompleted(null, ev));
        }

        private void GuardaPerfilOpcionesCompleted(object sender, GuardarPerfilOpcionCompletedEventArgs e)
        {

            IsDirty = false;
            // CargarOpciones();
            CollectionTemp = new ObservableCollection<PerfilOpcion>();
            ProxyAdministracion.ObtenerPerfilPorIdAsync(PerfilSeleccionado.idPerfil, ev =>
                        {
                            if (ev.Error != null)
                                return;
                            CollectionTemp = new ObservableCollection<PerfilOpcion>(ev.Result.PerfilOpcions);
                            CollectionTemp.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(CollectionTemp_CollectionChanged);
                            CollectionTemp.ToList().ForEach(a =>
                            {
                                ((INotifyPropertyChanged)a).PropertyChanged += new PropertyChangedEventHandler(ArbolOpcionesPerfilViewModel_PropertyChanged);
                            });
                        });

            OnSaveCompleted();
            OnEstadoProcesando(false);

        }
    }
}


